import asyncio
from typing import Dict

from app.models.database.models import ServiceConfig
from app.services.health.health_checker import health_checker
from app.services.monitoring.failure_detector import failure_detector
from app.services.switching.switch_manager import switch_manager
from app.core.config.database import get_db
import logging

logger = logging.getLogger(__name__)


class HealthCheckScheduler:
    """健康检查定时任务调度器"""

    def __init__(self):
        self.running = False
        self.tasks = {}
        self.check_intervals = {}

    async def start_monitoring(self):
        """启动监控"""
        if self.running:
            return

        self.running = True
        logger.info("Starting health check monitoring...")

        # 启动所有服务的健康检查
        db = next(get_db())
        try:
            services = db.query(ServiceConfig).filter(ServiceConfig.is_active == True).all()

            for service in services:
                await self.schedule_service_check(service)

        finally:
            db.close()

    async def stop_monitoring(self):
        """停止监控"""
        self.running = False

        # 取消所有任务
        for task in self.tasks.values():
            task.cancel()

        self.tasks.clear()
        logger.info("Health check monitoring stopped")

    async def schedule_service_check(self, service: ServiceConfig):
        """为单个服务安排健康检查"""

        if service.id in self.tasks:
            self.tasks[service.id].cancel()

        async def check_service_periodically():
            """定期执行健康检查"""
            while self.running:
                try:
                    await self._perform_health_check(service.id)

                    # 等待下一次检查
                    await asyncio.sleep(service.check_interval)

                except asyncio.CancelledError:
                    break
                except Exception as e:
                    logger.error(f"Error in health check for service {service.name}: {e}")
                    await asyncio.sleep(60)  # 出错后等待1分钟

        task = asyncio.create_task(check_service_periodically())
        self.tasks[service.id] = task
        self.check_intervals[service.id] = service.check_interval

        logger.info(f"Scheduled health check for service {service.name} "
                    f"every {service.check_interval} seconds")

    async def _perform_health_check(self, service_id: int):
        """执行健康检查"""

        db = next(get_db())
        try:
            service = db.query(ServiceConfig).filter(ServiceConfig.id == service_id).first()
            if not service:
                return

            # 执行健康检查
            health_result = await health_checker.check_service_health(service, db)

            # 分析健康状态
            analysis = failure_detector.analyze_service_health(service_id, db)

            # 如果需要切换，执行自动切换
            if analysis.get("should_switch", False):
                reason = analysis.get("switch_reason", "Automatic failure detection")

                await switch_manager.auto_switch_on_failure(
                    service_id=service_id,
                    failure_reason=reason,
                    db=db
                )

                logger.warning(
                    f"Auto-switch triggered for service {service.name}: {reason}"
                )

            # 记录健康检查日志
            logger.debug(
                f"Health check completed for {service.name}: "
                f"{health_result['status']} "
                f"({health_result.get('response_time', 'N/A')}ms)"
            )

        finally:
            db.close()

    async def update_service_schedule(self, service_id: int):
        """更新服务的检查计划"""

        db = next(get_db())
        try:
            service = db.query(ServiceConfig).filter(ServiceConfig.id == service_id).first()
            if service and service.is_active:
                await self.schedule_service_check(service)
            elif service.id in self.tasks:
                # 如果服务被禁用，取消检查
                self.tasks[service.id].cancel()
                del self.tasks[service.id]

        finally:
            db.close()

    def get_monitoring_status(self) -> Dict[str, any]:
        """获取监控状态"""

        return {
            "running": self.running,
            "monitored_services": len(self.tasks),
            "service_intervals": self.check_intervals
        }


# 全局调度器实例
scheduler = HealthCheckScheduler()


# 启动和停止函数
async def start_health_monitoring():
    """启动健康监控"""
    await scheduler.start_monitoring()


async def stop_health_monitoring():
    """停止健康监控"""
    await scheduler.stop_monitoring()


def get_monitoring_status():
    """获取监控状态"""
    return scheduler.get_monitoring_status()